package handler

import (
	"time"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"

	"hrms-api/model"
	"hrms-api/utils"
)

// UserRegisterRequest 用户注册请求
type UserRegisterRequest struct {
	Username string `json:"username" binding:"required,min=3,max=50"`
	Password string `json:"password" binding:"required,min=6"`
	Email    string `json:"email" binding:"required,email"`
}

// UserLoginRequest 用户登录请求
type UserLoginRequest struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

// UserUpdateRequest 用户信息更新请求
type UserUpdateRequest struct {
	Email   string `json:"email" binding:"omitempty,email"`
	Name    string `json:"name" binding:"omitempty"`
	Phone   string `json:"phone" binding:"omitempty"`
	Address string `json:"address" binding:"omitempty"`
	Avatar  string `json:"avatar" binding:"omitempty"`
}

// Register 用户注册
func Register(c *gin.Context) {
	var req UserRegisterRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		BadRequest(c, "Invalid request parameters")
		return
	}

	// 检查用户名是否已存在
	var existingUser model.User
	result := model.DB.Where("username = ?", req.Username).First(&existingUser)
	if result.Error != gorm.ErrRecordNotFound {
		BadRequest(c, "Username already exists")
		return
	}

	// 检查邮箱是否已存在
	result = model.DB.Where("email = ?", req.Email).First(&existingUser)
	if result.Error != gorm.ErrRecordNotFound {
		BadRequest(c, "Email already exists")
		return
	}

	// 创建新用户
	hashedPassword, err := utils.HashPassword(req.Password)
	if err != nil {
		InternalServerError(c, "Failed to process password")
		return
	}

	// 先创建用户基本信息，不包含角色关联
	user := model.User{
		Username: req.Username,
		Password: hashedPassword,
		Email:    req.Email,
		Status:   1, // 默认状态为正常
	}

	if err := model.DB.Create(&user).Error; err != nil {
		InternalServerError(c, "Failed to create user")
		return
	}

	// 查询candidate角色
	var candidateRole model.Role
	if err := model.DB.Where("name = ?", "candidate").First(&candidateRole).Error; err != nil {
		InternalServerError(c, "Failed to find candidate role")
		return
	}

	// 创建用户-角色关联
	userRole := model.UserRole{
		UserID: user.ID,
		RoleID: candidateRole.ID,
	}

	if err := model.DB.Create(&userRole).Error; err != nil {
		InternalServerError(c, "Failed to assign role to user")
		return
	}

	Success(c, gin.H{"id": user.ID})
}

// Login 用户登录
func Login(c *gin.Context) {
	var req UserLoginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		BadRequest(c, "Invalid request parameters")
		return
	}

	// 查找用户并预加载角色信息
	var user model.User
	result := model.DB.Preload("Roles").Where("username = ?", req.Username).First(&user)
	if result.Error != nil {
		Unauthorized(c, "Invalid username or password")
		return
	}

	// 验证密码
	if !utils.CheckPassword(req.Password, user.Password) {
		Unauthorized(c, "Invalid username or password")
		return
	}

	// 检查用户状态
	if user.Status != 1 {
		Forbidden(c, "Account is disabled")
		return
	}

	// 生成JWT token

	// 将roles转换为字符串
	rolesStr := ""
	for _, role := range user.Roles {
		rolesStr += role.Name + ","
	}
	if len(rolesStr) > 0 {
		rolesStr = rolesStr[:len(rolesStr)-1] // 移除最后一个逗号
	}
	token, err := utils.GenerateToken(user.ID, user.Username, rolesStr)
	if err != nil {
		InternalServerError(c, "Failed to generate token")
		return
	}

	Success(c, gin.H{
		"id":       user.ID,
		"username": user.Username,
		"roles":    user.Roles,
		"token":    token,
	})
}

// UserPasswordUpdateRequest 密码修改请求
type UserPasswordUpdateRequest struct {
	OldPassword string `json:"old_password" binding:"required"`
	NewPassword string `json:"new_password" binding:"required,min=6"`
}

// GetUserInfo 获取当前用户信息
func GetUserInfo(c *gin.Context) {
	// 从上下文中获取当前用户ID
	userID, exists := c.Get("user_id")
	if !exists {
		Unauthorized(c, "User not authenticated")
		return
	}

	var user model.User
	// 预加载用户角色信息
	result := model.DB.Preload("Roles").First(&user, userID)
	if result.Error != nil {
		NotFound(c, "User not found")
		return
	}

	Success(c, user)
}

// UpdateUserInfo 更新当前用户信息
func UpdateUserInfo(c *gin.Context) {
	// 从上下文中获取当前用户ID
	userID, exists := c.Get("user_id")
	if !exists {
		Unauthorized(c, "User not authenticated")
		return
	}

	var req UserUpdateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		BadRequest(c, "Invalid request parameters")
		return
	}

	var user model.User
	result := model.DB.First(&user, userID)
	if result.Error != nil {
		NotFound(c, "User not found")
		return
	}

	// 更新用户信息
	updates := map[string]interface{}{}
	if req.Email != "" {
		// 检查邮箱是否已被其他用户使用
		var existingUser model.User
		result := model.DB.Where("email = ? AND id != ?", req.Email, userID).First(&existingUser)
		if result.Error != gorm.ErrRecordNotFound {
			BadRequest(c, "Email already exists")
			return
		}
		updates["email"] = req.Email
	}
	if req.Name != "" {
		updates["name"] = req.Name
	}
	if req.Phone != "" {
		updates["phone"] = req.Phone
	}
	if req.Address != "" {
		updates["address"] = req.Address
	}
	if req.Avatar != "" {
		updates["avatar"] = req.Avatar
	}
	updates["updated_at"] = time.Now()

	if err := model.DB.Model(&user).Updates(updates).Error; err != nil {
		InternalServerError(c, "Failed to update user information")
		return
	}

	Success(c, gin.H{"message": "User information updated successfully"})
}

// UpdatePassword 修改当前用户密码
func UpdatePassword(c *gin.Context) {
	// 从上下文中获取当前用户ID
	userID, exists := c.Get("user_id")
	if !exists {
		Unauthorized(c, "User not authenticated")
		return
	}

	var req UserPasswordUpdateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		BadRequest(c, "Invalid request parameters")
		return
	}

	// 获取用户信息
	var user model.User
	result := model.DB.First(&user, userID)
	if result.Error != nil {
		NotFound(c, "User not found")
		return
	}

	// 验证旧密码
	if !utils.CheckPassword(req.OldPassword, user.Password) {
		BadRequest(c, "Old password is incorrect")
		return
	}

	// 生成新密码的哈希值
	hashedPassword, err := utils.HashPassword(req.NewPassword)
	if err != nil {
		InternalServerError(c, "Failed to process new password")
		return
	}

	// 更新密码
	if err := model.DB.Model(&user).Update("password", hashedPassword).Error; err != nil {
		InternalServerError(c, "Failed to update password")
		return
	}

	Success(c, gin.H{"message": "Password updated successfully"})
}
